﻿using H.DML.See;
using H.Eyes;
using H.Types;
using H.Utils.DataStruct;
using System;
using System.Reflection;
using System.Runtime.InteropServices;

namespace H.DML
{
    /// <summary>
    /// 表示一个大漠插件
    /// </summary>
    public class DMEye : IEye
    {
        #region 配置性常量
        /// <summary>
        /// 大漠dmreg
        /// </summary>
        public const string DM_REGDLLPATH = "32668823.dll";

        /// <summary>
        /// 大漠插件主体
        /// </summary>
        public const string DM_DLLPATH = "3266456.dll";

        /// <summary>
        /// 大漠插件的对象名(通用版的值为dm.dmsoft)
        /// </summary>
        public const string DM_CLASSNAME = "ll.dxiang";

        /// <summary>
        /// 
        /// </summary>
        public const string FN_SETDLLPATH = "HCKvyYKUnXiRPFY";

        /// <summary>
        /// FindPicMem函数别名
        /// </summary>
        public const string FN_FINDPICMEM = "LwGKX";

        /// <summary>
        /// FindPicMemEx函数别名
        /// </summary>
        public const string FN_FINDPICMEMEX = "ougYMmYHuGzUjnz";

        /// <summary>
        /// FindColor函数别名
        /// </summary>
        public const string FN_FINDCOLOR = "rbAMttW";

        /// <summary>
        /// FindColorEx函数别名
        /// </summary>
        public const string FN_FINDCOLOREX = "RhIgoSftpzUgdWM";

        /// <summary>
        /// SetDisplayInput函数别名
        /// </summary>
        public const string FN_SETDISPLAYINPUT = "bynwP";

        #endregion

        #region 内部使用到的外部导入函数
        /// <summary>
        /// 用于免注册调用大漠插件
        /// </summary>
        /// <param name="path"></param>
        /// <param name="mode"></param>
        /// <returns></returns>
        [DllImport(DM_REGDLLPATH, CharSet = CharSet.Unicode, EntryPoint = FN_SETDLLPATH)]
        private static extern int SetDllPath(string path, int mode);
        #endregion

        #region 内部变量

        /// <summary>
        /// 大漠类型
        /// </summary>
        public readonly static Type _DMType;

        /// <summary>
        /// 大漠插件实例
        /// </summary>
        public readonly object _DM;

        /// <summary>
        /// 表示被匹配图片的内存
        /// </summary>
        private readonly MemBlock _DisplayMem = new MemBlock();

        /// <summary>
        /// 查找图片函数调用修饰符
        /// </summary>
        public static readonly ParameterModifier[] FindPicMods;

        /// <summary>
        /// 查找颜色函数调用修饰符
        /// </summary>
        public static readonly ParameterModifier[] FindColorMods;

        #endregion

        ///<inheritdoc/>
        public IEyeOption DefaultOption { get; } = new DMOption();

        static DMEye()
        {
            SetDllPath(HService.GetEnvPath("lib\\" + DM_DLLPATH), 0);
            _DMType = Type.GetTypeFromProgID(DM_CLASSNAME) ?? throw new Exception("加载插件失败");


            FindPicMods = new ParameterModifier[]{
                new ParameterModifier(10)
            };
            FindPicMods[0][8] = true;
            FindPicMods[0][9] = true;

            FindColorMods = new ParameterModifier[]
            {
                new ParameterModifier(9)
            };

            FindColorMods[0][7] = true;
            FindColorMods[0][8] = true;

        }

        /// <summary>
        /// 初始化一个大漠插件
        /// </summary>
        public DMEye()
        {
            _DM = Activator.CreateInstance(_DMType) ?? throw new Exception("初始化失败");
        }

        /// <inheritdoc/>
        public IEyeOption CreateOption()
        {
            return new DMOption();
        }

        /// <inheritdoc/>
        public ISee FindColor(params RGB[] colors)
        {
            return new DMColorSee(this, colors, DefaultOption as DMOption);
        }

        /// <inheritdoc/>
        public ISee FindColor(IEyeOption option, params RGB[] colors)
        {
            return new DMColorSee(this, colors, (option ?? DefaultOption) as DMOption);
        }



        /// <summary>
        /// 原始查找图片函数(大漠封装)
        /// </summary>
        /// <param name="rect">待查找的区域</param>
        /// <param name="picInfo">图片信息</param>
        /// <param name="deltaColor">偏色</param>
        /// <param name="similar">相似度</param>
        /// <param name="direction">方向</param>
        /// <param name="matchPos">输出找到的坐标</param>
        /// <returns>返回找到的坐标</returns>
        public int FindPicMem(Rect rect, string picInfo, string deltaColor, double similar, int direction, out Pos matchPos)
        {
            object[] args = new object[]
            {
                rect.Left,
                rect.Top,
                rect.Right,
                rect.Bottom,
                picInfo,
                deltaColor,
                similar,
                direction,
                null,
                null
            };
            int ret = (int)_DMType.InvokeMember(FN_FINDPICMEM, BindingFlags.InvokeMethod, null, _DM, args, FindPicMods, null, null);
            if (ret != -1)
            {
                matchPos = new Pos((int)args[8], (int)args[9]);
            }
            else
            {
                matchPos = Pos.Empty;
            }
            return ret;
        }

        /// <summary>
        /// 原始查找图片函数(大漠封装)
        /// </summary>
        /// <param name="rect">待查找的区域</param>
        /// <param name="picInfo">图片信息</param>
        /// <param name="deltaColor">偏色</param>
        /// <param name="similar">相似度</param>
        /// <param name="direction">找图方向</param>
        /// <returns>返回找到的坐标</returns>
        public string FindPicMemEx(Rect rect, string picInfo, string deltaColor, double similar, int direction)
        {
            object[] args = new object[]
            {
                rect.Left,
                rect.Top,
                rect.Right,
                rect.Bottom,
                picInfo,
                deltaColor,
                similar,
                direction
            };
            return (string)_DMType.InvokeMember(FN_FINDPICMEMEX, BindingFlags.InvokeMethod, null, _DM, args);
        }

        /// <summary>
        /// 原始查找颜色函数(大漠封装)
        /// </summary>
        /// <param name="rect">待查找的区域</param>
        /// <param name="colors">颜色信息</param>
        /// <param name="similar">相似度</param>
        /// <param name="direction">方向</param>
        /// <param name="matchPos">输出找到的坐标</param>
        /// <returns>返回找到的坐标</returns>
        public int FindColor(Rect rect, string colors, double similar, int direction, out Pos matchPos)
        {
            object[] args = new object[]
            {
                rect.Left,
                rect.Top,
                rect.Right,
                rect.Bottom,
                colors,
                similar,
                direction,
                null,
                null
            };
            int ret = (int)_DMType.InvokeMember(FN_FINDCOLOR, BindingFlags.InvokeMethod, null, _DM, args, FindColorMods, null, null);
            if (ret != -1)
            {
                matchPos = new Pos((int)args[7], (int)args[8]);
            }
            else
            {
                matchPos = Pos.Empty;
            }
            return ret;
        }

        /// <summary>
        /// 原始查找颜色函数(大漠封装)
        /// </summary>
        /// <param name="rect">待查找的区域</param>
        /// <param name="colors">颜色信息</param>
        /// <param name="similar">相似度</param>
        /// <param name="direction">找图方向</param>
        /// <returns>返回找到的坐标</returns>
        public string FindColorEx(Rect rect, string colors, double similar, int direction)
        {
            object[] args = new object[]
            {
                rect.Left,
                rect.Top,
                rect.Right,
                rect.Bottom,
                colors,
                similar,
                direction
            };
            return (string)_DMType.InvokeMember(FN_FINDCOLOREX, BindingFlags.InvokeMethod, null, _DM, args);
        }

        /// <summary>
        /// 设置图色查找查找源(大漠封装)
        /// </summary>
        /// <param name="mode">查找源模式字符串</param>
        /// <returns>返回找到的坐标</returns>
        public int SetDisplayInput(string mode)
        {
            object[] args = new object[]
            {
               mode
            };
            return (int)_DMType.InvokeMember(FN_SETDISPLAYINPUT, BindingFlags.InvokeMethod, null, _DM, args);
        }

        /// <inheritdoc/>
        public ISee FindPic(IEyeOption option, params IImgEntity[] imgs)
        {
            return new DMImgSee(this, imgs, (option ?? DefaultOption) as DMOption);
        }

        /// <inheritdoc/>
        public ISee FindPic(params IImgEntity[] imgs)
        {
            return new DMImgSee(this, imgs, DefaultOption as DMOption);
        }

        /// <inheritdoc/>
        public ISee FindPicB(IEyeOption option, params IImgEntity[] imgs)
        {
            return new DMImgSeeB(this, imgs, (option ?? DefaultOption) as DMOption);
        }

        /// <inheritdoc/>
        public ISee FindPicB(params IImgEntity[] imgs)
        {
            return new DMImgSeeB(this, imgs, DefaultOption as DMOption);
        }

        /// <inheritdoc/>
        public bool SetDisplay(byte[] display = null)
        {
            if (display != null)
            {
                _DisplayMem.SetBytes(display);
                return SetDisplayInput($"mem:{_DisplayMem.Pointer.ToInt32()},{_DisplayMem.Size}") == 1;
            }
            else
            {
                return SetDisplayInput("screen") == 1;
            }
        }

        /// <summary>
        /// 释放资源
        /// </summary>
        /// <param name="disposing"></param>
        protected void Dispose(bool disposing)
        {
            //不需要手动释放
        }

        /// <summary>
        /// 释放资源
        /// </summary>
        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        /// <summary>
        /// 析构函数
        /// </summary>
        ~DMEye()
        {
            Dispose(false);
        }
    }
}
